#ifndef __FLOAT__
#define __FLOAT__

#include <iostream>
#include <string>

using namespace std;
typedef unsigned char byte;


/*
 * LA IDEA DE ESTA IMPLEMENTACION ES LA SIGUIENTE
 * TENEMOS EL SIGNO, EL EXPONENTE(falta probar cosas negativas)
 * Y LA MANTISA, QUE ES UN ARRAY DE BYTE (entoces la base del exponente es 8)
 * PARA LA MANTISA TAMBIEN SE DEFINIO UNA VAR 
 * LLAMADA PRESICION QUE INDICA LA LONGITUD
 * 
 * LA IDEA DE LA MANTISA ES QUE ES EL NUMEROQUE ESTA ENTRE EL 0 Y EL 1
 */
class Float{
	
	public:
		/**
		 * Constructores
		 */
		Float();
		//Float(const string&);
		Float(const float&);

		/**
		 * operadores de comparacion
		 */
		bool operator==(const Float&) const;
		
		/**
		 * operadores aritmeticos
		 */
		//Float operator+(const Float&);
		friend Float operator+(const Float&, const Float&);
		friend Float operator*(const Float&, const Float&);

		/**
		 * operadores de asignacion y aritmeticos
		 */
		void operator=(const Float&);
		

		byte* mantisa;
		int presicion;
		long int exponente;
		bool signo;
	private:
};

Float::Float() : mantisa(NULL), presicion(0), exponente(0), signo(false)  {}

//ESTO AHROA ESTA QUE CREE LOS NUMEROS SOLOS(o sea numeros fijos)
Float::Float(const float& f) {
	if(f==1) {
		signo = false;
		exponente = 4;
		presicion = 2;
		mantisa = new byte[2];
		mantisa[0] = 0x11;
		mantisa[1] = 0x22;
	} else if(f==2) {
		signo = false;
		exponente = 4;
		presicion = 2;
		mantisa = new byte[2];
		mantisa[0] = 0x11;
		mantisa[1] = 0xE2;
	} else if(f==3) {
		signo = false;
		exponente = 4;
		presicion = 4;
		mantisa = new byte[4];
		mantisa[0] = 0x11;
		mantisa[1] = 0xCC;
		mantisa[2] = 0x33;
		mantisa[3] = 0x44;
	} else if(f==4) {
		signo = false;
		exponente = 6;
		presicion = 4;
		mantisa = new byte[4];
		mantisa[0] = 0x11;
		mantisa[1] = 0x80;
		mantisa[2] = 0x33;
		mantisa[3] = 0x44;
	}
}


/*
 * COMENTARIO: 
 * ESTA BASTNATE AVANZADO, POR AHORA SUMA DOS FLOAT 
 * CON EXPONENTES IGUALES O DIFERNTES, CON PRESICION IGUALES O DIFERENTES
 * Y HACE CARRY ENTRE COSAS
 * ME FALTA:
 * 1)QUE PASA CON  LOS SIGNOS
 * 2)SI QUEDA UN CARRY AL FINAL, MOVER TODo(una paja :P)
 */
Float operator+(const Float& f1, const Float& f2) {
	Float ret;
	if(f1.exponente == f2.exponente) {
		ret.signo = f2.signo; //falta ver el singo que onda
		ret.exponente = f2.exponente;
		if(f1.presicion == f2.presicion) {
			ret.presicion = f1.presicion;
			ret.mantisa = new byte[ret.presicion];
			bool hayCarry = false;
			for(int i=ret.presicion-1;i>=0;i--) {
				ret.mantisa[i] = (f1.mantisa[i]+f2.mantisa[i] + (hayCarry?1:0));
				hayCarry = ret.mantisa[i] < f1.mantisa[i] || ret.mantisa[i] < f2.mantisa[i];
			}
		} else { //diferente presicion
			if(f1.presicion < f2.presicion) { //se puede poner todos en un else if pero asi queda mas claro
				ret.presicion = f2.presicion;
				ret.mantisa = new byte[ret.presicion];
				for(int i=f2.presicion-1;i>=f1.presicion;i--) {
					ret.mantisa[i] = f2.mantisa[i];
				}
				bool hayCarry = false;
				for(int i=f1.presicion-1;i>=0;i--) {
					ret.mantisa[i] = (f1.mantisa[i] + f2.mantisa[i] + (hayCarry?1:0));
					hayCarry = ret.mantisa[i] < f1.mantisa[i] || ret.mantisa[i] < f2.mantisa[i];
				}
			} else { //aux2.presicion < f1.presicion
				ret.presicion = f1.presicion;
				ret.mantisa = new byte[ret.presicion];
				for(int i=f1.presicion-1;i>=f2.presicion;i--) {
					ret.mantisa[i] = f1.mantisa[i];
				}
				bool hayCarry = false;
				for(int i=f2.presicion-1;i>=0;i--) {
					ret.mantisa[i] = (f1.mantisa[i] + f2.mantisa[i] + (hayCarry?1:0));
					hayCarry = ret.mantisa[i] < f1.mantisa[i] || ret.mantisa[i] < f2.mantisa[i];
				}
			}
		}
	} else {
		if(f1.exponente < f2.exponente) {
			Float aux;
			aux = f1;
			long int dif = f2.exponente - f1.exponente;
			long int nuevaP = f1.presicion + dif;
			byte *mantisaAux = new byte[nuevaP];
			for(int i=0;i<dif;i++) {
				mantisaAux[i] = 0;
			}
			for(int i=dif;i<nuevaP;i++) {
				mantisaAux[i] = f1.mantisa[i-dif];
			}
			delete [] aux.mantisa;
			aux.mantisa = mantisaAux;
			aux.exponente = f2.exponente;
			aux.presicion = f1.presicion + dif;
			return aux+f2;
		} else {
			Float aux;
			aux = f2;
			long int dif = f1.exponente - f2.exponente;
			long int nuevaP = f2.presicion + dif;
			byte *mantisaAux = new byte[nuevaP];
			for(int i=0;i<dif;i++) {
				mantisaAux[i] = 0;
			}
			for(int i=dif;i<nuevaP;i++) {
				mantisaAux[i] = f2.mantisa[i-dif];
			}
			delete [] aux.mantisa;
			aux.mantisa = mantisaAux;
			aux.exponente = f1.exponente;
			aux.presicion = f2.presicion + dif;
			return f1+aux;
		}
	}
	
	//devuelve, falta verificar si quedo un carry
	//me parece q lo del carry es simplemtne ver
	//si ret[0] < f1[0] && < f2[0], dejo un pseaudo codigo comentado
//	if(ret[0] < f1[0] && ret[0] < f2[0]) {
//		byte *mantisa = new byte[ret.presicion+1];
//		mantisa[0] = 1;
//		for(int i=1;i<ret.presicion;i++)
//			mantisa[i] = ret.mantisa[i-1];
//		delete [] ret.mantisa;
//		ret.mantisa = &mantisa;
//		ret.presicion++;
//		ret.exponente++;
//		return ret;
//	} else {
//		return ret;
//	}
	return ret;
}

/*
 * FALTA
 */
Float operator*(const Float& f1, const Float& f2) {
	Float ret;
	return ret;
}

void Float::operator=(const Float& f) {
	signo = f.signo;
	exponente = f.exponente;
	presicion = f.presicion;
	if(!&mantisa == NULL)
		delete [] mantisa;
	mantisa = new byte[presicion];
	for(int i=0;i<presicion;i++)
		mantisa[i] = f.mantisa[i];
}



bool Float::operator== (const Float& f) const {
	if(this!=&f) {
		bool ret = exponente == f.exponente;
		ret = ret && (signo == f.signo);
		ret = ret && (presicion == f.presicion);
		for(int i=0;ret && i<presicion;i++)
			ret = mantisa[i] == f.mantisa[i];
		return ret;
	} 
	return true;
}

ostream& operator<<(ostream& out, const Float& f) {
	/* out << "signo: " << f.signo;
	out << ", exponente: " << f.exponente;
	out << ", mantisa: ";
	for(int i=0;i<f.presicion;i++)
		out << (int)f.mantisa[i] << "_";
	out << endl; */
		
	return out;
}

#endif
